module arm.flash;


import chip;
//import std.internal.math.biguintcore;

import arm.misc;
/// 判定有对应总线外设
private enum bool hasBusPeriph = HasPeriph!("FLASH");

static if(hasBusPeriph):
import arm.bus;


static interface Flash 
{
    enum mBase = Peripherals.FLASH;
    deprecated
    package{
        @property static void MMIO_ACR(string fn,T = uint)(T v) if(__traits(hasMember, mBase, "ACR"))
            => MMIO_Bitfield!("ACR",fn,T)(v);
        @property static T MMIO_ACR(string fn,T = uint)() if(__traits(hasMember, mBase, "ACR"))
            => MMIO_Bitfield!("ACR",fn)();
        
        @property static T MMIO_KEYR(string fn,T = uint)() if(__traits(hasMember, mBase, "KEYR"))
            => MMIO_Bitfield!("KEYR",fn)();

        @property static T MMIO_OPTKEYR(string fn,T = uint)() if(__traits(hasMember, mBase, "OPTKEYR"))
            => MMIO_Bitfield!("OPTKEYR",fn)();

        @property static void MMIO_SR(string fn,T = uint)(T v) if(__traits(hasMember, mBase, "SR"))
            => MMIO_Bitfield!("SR",fn,T)(v);
        @property static T MMIO_SR(string fn,T = uint)() if(__traits(hasMember, mBase, "SR"))
            => MMIO_Bitfield!("SR",fn)();
        
        @property static void MMIO_CR(string fn,T = uint)(T v) if(__traits(hasMember, mBase, "CR"))
            => MMIO_Bitfield!("CR",fn,T)(v);
        @property static T MMIO_CR(string fn,T = uint)() if(__traits(hasMember, mBase, "CR"))
            => MMIO_Bitfield!("CR",fn)();

        @property static void MMIO_OPTCR(string fn,T = uint)(T v) if(__traits(hasMember, mBase, "OPTCR"))
            => MMIO_Bitfield!("OPTCR",fn,T)(v);
        @property static T MMIO_OPTCR(string fn,T = uint)() if(__traits(hasMember, mBase, "OPTCR"))
            => MMIO_Bitfield!("OPTCR",fn)();
    }

    /// 判定繁忙
    static bool isBusy()
    {
        //return MMIO_Bitfield!("SR","BSY")() != 0;
        return mBase.SR.BSY() !=0;
    }

    static void EnablePrefetch()
    {
        //MMIO_Bitfield!("ACR","PRFTEN")(1);
        mBase.ACR.PRFTEN(1);
    };
    /// 设置访问延时
    static void Latency(uint v) @property
    in(v < mBase.mask_ACR.LATENCY)
    {
        //MMIO_Bitfield!("ACR","LATENCY")(v);
        mBase.ACR.LATENCY(v);
    }
    static uint Latency() @property
    {
        return mBase.ACR.LATENCY();
    }
    /**
    * 等待繁忙超时
    * Params:
    *   timeout = 超时时间 ms ,如SysTick时钟使能则使用SysTick计数
    */
    static void WaitBusy( uint timeout = 0x2710)
    {
        import arm.stk;
        //bool useSystick = SysTick.isEnable();

        while(isBusy() && (timeout > 0))
        {
            timeout--;
        }
    }

    pragma(crt_constructor,CrtPriority!(FlagCrt.FLASH,0))
    static this()
    {
        enum uint nLATENCY = GetConfig!("Flash_LATENCY");
        auto oldval = mBase.ACR;
        oldval.ICEN = GetConfig!("ICacheEnable")?1:0;
        oldval.DCEN = GetConfig!("DCacheEnable")?1:0;
        oldval.PRFTEN = GetConfig!("PrefetchEnable")?1:0;
        oldval.LATENCY = GetConfig!("Flash_LATENCY");

        mBase.ACR = oldval;

        /// 等待稳定
        while(Latency() != nLATENCY)
        {

        }

    }

}


